/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.app.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.exception.BizServiceException;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.market.base.app.mapper.IAppMapper;
import net.siufung.market.base.app.mapper.entity.App;
import net.siufung.market.base.app.service.IAppService;
import net.siufung.market.base.oauth.mapper.entity.ClientDetails;
import net.siufung.market.base.oauth.service.IClientDetailsService;
import net.siufung.mybatis.base.BaseServiceImpl;
import net.siufung.security.api.service.passwd.IClientPasswdService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Objects;

/**
 * 应用信息 数据服务实现
 *
 * @author 陈建峰
 * @date 2023-01-12 16:24:13
 * @since v1.0.0
 */
@Slf4j
@RequiredArgsConstructor
@Service(value = "appService")
@Transactional(rollbackFor = Exception.class)
public class AppServiceImpl extends BaseServiceImpl<IAppMapper, App> implements IAppService {
    
    private final IClientDetailsService clientDetailsService;
    private final IClientPasswdService clientPasswdService;


    @Override
    public boolean save(App app) {
        if(Strings.isNullOrEmpty(app.getAppCode())){
            app.setAppCode(getRandomAppCode(16));
        }
        if(super.save(app)){
            this.saveClientDetails(app);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 私有方法保存应用授权
     * @param app 应用授权
     */
    private void saveClientDetails(App app) {
        ClientDetails clientDetails = new ClientDetails();
        clientDetails.setClientId(app.getClientId());
        clientDetails.setResourceIds("");
        clientDetails.setClientSecret(clientPasswdService.encode(app.getClientSecret()));
        clientDetails.setScope(app.getClientScope());
        clientDetails.setAuthorizedGrantTypes(app.getClientGrantTypes());
        clientDetails.setWebServerRedirectUri(app.getAppPath());
        clientDetails.setAuthorities("");
        clientDetails.setAccessTokenValidity(app.getAccessTokenSec());
        clientDetails.setRefreshTokenValidity(app.getRefreshTokenSec());
        clientDetails.setAdditionalInformation("");
        clientDetails.setAutoapprove("");
        clientDetailsService.save(clientDetails);
    }

    @Override
    public boolean updateStatusById(Serializable id, DeletedEnum deletedEnum) {
        if(super.update(
                new LambdaUpdateWrapper<App>()
                        .eq(App::getId, id)
                        .set(App::getDeleted, deletedEnum.getValue()))){
            App app = super.getById(id);
            if (DeletedEnum.IS.equals(deletedEnum)) {
                clientDetailsService.remove(new LambdaQueryWrapper<ClientDetails>()
                        .eq(ClientDetails::getClientId, app.getClientId()));
            } else {
                this.saveClientDetails(app);
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public boolean updateById(App app) {
        if(super.updateById(app)){
            clientDetailsService.update(new LambdaUpdateWrapper<ClientDetails>()
                    .set(ClientDetails::getClientSecret, clientPasswdService.encode(app.getClientSecret()))
                    .set(ClientDetails::getAuthorizedGrantTypes, app.getClientGrantTypes())
                    .set(ClientDetails::getWebServerRedirectUri, app.getAppPath())
                    .set(ClientDetails::getAccessTokenValidity, app.getAccessTokenSec())
                    .set(ClientDetails::getRefreshTokenValidity, app.getRefreshTokenSec())
                    .eq(ClientDetails::getClientId, app.getClientId()));
            return Boolean.TRUE;
        };
        return Boolean.FALSE;
    }

    @Override
    public boolean removeById(Serializable id) {
        App app = getBaseMapper().selectById(id);
        if(Objects.isNull(app)){
            throw new BizServiceException("应用不存在！");
        }
        if(super.removeById(id)){
            clientDetailsService.remove(new LambdaQueryWrapper<ClientDetails>()
                    .eq(ClientDetails::getClientId, app.getClientId()));
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 获得随机应用编码
     * @param length 随机码长度
     * @return String
     */
    private String getRandomAppCode(int length){
        String menuCode = RandomUtil.randomString(length);
        if(getBaseMapper().selectCount(
                new LambdaQueryWrapper<App>().eq(App::getAppCode, menuCode)) > 0){
            menuCode = getRandomAppCode(length);
        }
        return menuCode;
    }
}